/**
	******************************************************************************
	* @file
	* @author
	* @version
	* @date
	* @brief
	* @function List:
	******************************************************************************
	* @attention
	*
	*
	* <h2><center>&copy; COPYRIGHT 2021 </center></h2>
	******************************************************************************
	* @History:
	* @Author:
	* @Data:
	* @Version:
*/

#include "crc.h"
#include "common_types.h"


#ifdef CRC_USE_TABLE
#define CRC8_BIT(x)  (1u << (x))

#ifdef CRC_TABLE_IS_CONST

MEMORY_MAP_ROM_DATA_FOR_ASIL const u8 crc8_table[CRC8_ID_MAX][256]=
{
	{	//多项式 1D  初始化值 FF 异或值 FF
		0x00, 0x1D, 0x3A, 0x27, 0x74, 0x69, 0x4E, 0x53, 0xE8, 0xF5, 0xD2, 0xCF, 0x9C, 0x81, 0xA6, 0xBB,
		0xCD, 0xD0, 0xF7, 0xEA, 0xB9, 0xA4, 0x83, 0x9E, 0x25, 0x38, 0x1F, 0x02, 0x51, 0x4C, 0x6B, 0x76,
		0x87, 0x9A, 0xBD, 0xA0, 0xF3, 0xEE, 0xC9, 0xD4, 0x6F, 0x72, 0x55, 0x48, 0x1B, 0x06, 0x21, 0x3C,
		0x4A, 0x57, 0x70, 0x6D, 0x3E, 0x23, 0x04, 0x19, 0xA2, 0xBF, 0x98, 0x85, 0xD6, 0xCB, 0xEC, 0xF1,
		0x13, 0x0E, 0x29, 0x34, 0x67, 0x7A, 0x5D, 0x40, 0xFB, 0xE6, 0xC1, 0xDC, 0x8F, 0x92, 0xB5, 0xA8,
		0xDE, 0xC3, 0xE4, 0xF9, 0xAA, 0xB7, 0x90, 0x8D, 0x36, 0x2B, 0x0C, 0x11, 0x42, 0x5F, 0x78, 0x65,
		0x94, 0x89, 0xAE, 0xB3, 0xE0, 0xFD, 0xDA, 0xC7, 0x7C, 0x61, 0x46, 0x5B, 0x08, 0x15, 0x32, 0x2F,
		0x59, 0x44, 0x63, 0x7E, 0x2D, 0x30, 0x17, 0x0A, 0xB1, 0xAC, 0x8B, 0x96, 0xC5, 0xD8, 0xFF, 0xE2,
		0x26, 0x3B, 0x1C, 0x01, 0x52, 0x4F, 0x68, 0x75, 0xCE, 0xD3, 0xF4, 0xE9, 0xBA, 0xA7, 0x80, 0x9D,
		0xEB, 0xF6, 0xD1, 0xCC, 0x9F, 0x82, 0xA5, 0xB8, 0x03, 0x1E, 0x39, 0x24, 0x77, 0x6A, 0x4D, 0x50,
		0xA1, 0xBC, 0x9B, 0x86, 0xD5, 0xC8, 0xEF, 0xF2, 0x49, 0x54, 0x73, 0x6E, 0x3D, 0x20, 0x07, 0x1A,
		0x6C, 0x71, 0x56, 0x4B, 0x18, 0x05, 0x22, 0x3F, 0x84, 0x99, 0xBE, 0xA3, 0xF0, 0xED, 0xCA, 0xD7,
		0x35, 0x28, 0x0F, 0x12, 0x41, 0x5C, 0x7B, 0x66, 0xDD, 0xC0, 0xE7, 0xFA, 0xA9, 0xB4, 0x93, 0x8E,
		0xF8, 0xE5, 0xC2, 0xDF, 0x8C, 0x91, 0xB6, 0xAB, 0x10, 0x0D, 0x2A, 0x37, 0x64, 0x79, 0x5E, 0x43,
		0xB2, 0xAF, 0x88, 0x95, 0xC6, 0xDB, 0xFC, 0xE1, 0x5A, 0x47, 0x60, 0x7D, 0x2E, 0x33, 0x14, 0x09,
		0x7F, 0x62, 0x45, 0x58, 0x0B, 0x16, 0x31, 0x2C, 0x97, 0x8A, 0xAD, 0xB0, 0xE3, 0xFE, 0xD9, 0xC4
	},
	{	//多项式 1D  初始化值 00 异或值 00
		0x00, 0x1D, 0x3A, 0x27, 0x74, 0x69, 0x4E, 0x53, 0xE8, 0xF5, 0xD2, 0xCF, 0x9C, 0x81, 0xA6, 0xBB,
		0xCD, 0xD0, 0xF7, 0xEA, 0xB9, 0xA4, 0x83, 0x9E, 0x25, 0x38, 0x1F, 0x02, 0x51, 0x4C, 0x6B, 0x76,
		0x87, 0x9A, 0xBD, 0xA0, 0xF3, 0xEE, 0xC9, 0xD4, 0x6F, 0x72, 0x55, 0x48, 0x1B, 0x06, 0x21, 0x3C,
		0x4A, 0x57, 0x70, 0x6D, 0x3E, 0x23, 0x04, 0x19, 0xA2, 0xBF, 0x98, 0x85, 0xD6, 0xCB, 0xEC, 0xF1,
		0x13, 0x0E, 0x29, 0x34, 0x67, 0x7A, 0x5D, 0x40, 0xFB, 0xE6, 0xC1, 0xDC, 0x8F, 0x92, 0xB5, 0xA8,
		0xDE, 0xC3, 0xE4, 0xF9, 0xAA, 0xB7, 0x90, 0x8D, 0x36, 0x2B, 0x0C, 0x11, 0x42, 0x5F, 0x78, 0x65,
		0x94, 0x89, 0xAE, 0xB3, 0xE0, 0xFD, 0xDA, 0xC7, 0x7C, 0x61, 0x46, 0x5B, 0x08, 0x15, 0x32, 0x2F,
		0x59, 0x44, 0x63, 0x7E, 0x2D, 0x30, 0x17, 0x0A, 0xB1, 0xAC, 0x8B, 0x96, 0xC5, 0xD8, 0xFF, 0xE2,
		0x26, 0x3B, 0x1C, 0x01, 0x52, 0x4F, 0x68, 0x75, 0xCE, 0xD3, 0xF4, 0xE9, 0xBA, 0xA7, 0x80, 0x9D,
		0xEB, 0xF6, 0xD1, 0xCC, 0x9F, 0x82, 0xA5, 0xB8, 0x03, 0x1E, 0x39, 0x24, 0x77, 0x6A, 0x4D, 0x50,
		0xA1, 0xBC, 0x9B, 0x86, 0xD5, 0xC8, 0xEF, 0xF2, 0x49, 0x54, 0x73, 0x6E, 0x3D, 0x20, 0x07, 0x1A,
		0x6C, 0x71, 0x56, 0x4B, 0x18, 0x05, 0x22, 0x3F, 0x84, 0x99, 0xBE, 0xA3, 0xF0, 0xED, 0xCA, 0xD7,
		0x35, 0x28, 0x0F, 0x12, 0x41, 0x5C, 0x7B, 0x66, 0xDD, 0xC0, 0xE7, 0xFA, 0xA9, 0xB4, 0x93, 0x8E,
		0xF8, 0xE5, 0xC2, 0xDF, 0x8C, 0x91, 0xB6, 0xAB, 0x10, 0x0D, 0x2A, 0x37, 0x64, 0x79, 0x5E, 0x43,
		0xB2, 0xAF, 0x88, 0x95, 0xC6, 0xDB, 0xFC, 0xE1, 0x5A, 0x47, 0x60, 0x7D, 0x2E, 0x33, 0x14, 0x09,
		0x7F, 0x62, 0x45, 0x58, 0x0B, 0x16, 0x31, 0x2C, 0x97, 0x8A, 0xAD, 0xB0, 0xE3, 0xFE, 0xD9, 0xC4
	}
};

#else

MEMORY_MAP_RAM_FOR_ASIL ENABLE_STATIC_FOR_ASIL u8 crc8_table[CRC8_ID_MAX][256] = {0u};

#endif

typedef struct
{
	u8 width;
	u8  poly;
	u8  init;
	u8   refin;
	u8   refout;
	u8  xorout;
}crc8_info_s;

MEMORY_MAP_RAM_FOR_ASIL ENABLE_STATIC_FOR_ASIL crc8_info_s crc_struct[CRC8_ID_MAX] =
{
	{8, CRC8_L1_POLY_VALUE, CRC8_L1_INIT_VALUE, 0,  0,   CRC8_L1_XOR_VALUE},    //CRC8_SAE J1850
	{8, CRC8_L2_POLY_VALUE, CRC8_L2_INIT_VALUE, 0,  0,   CRC8_L2_XOR_VALUE},    //CRC8_SAE J1850
};


//位逆转
MEMORY_MAP_ROM_FOR_ASIL u8 crc8_reflected(u8 input_value, u8 bits)
{
	u8 var = 0u;
	u8 l_bits = bits;
	while(l_bits)
	{
		l_bits -= 1u;
		var <<= 1;
		if (input_value & 0x01u)
		{
			var |= 1u;
		}
		input_value >>= 1u;
	}
	return var;
}

MEMORY_MAP_ROM_FOR_ASIL void crc8_table_init(u8 id)	/*PRQA S 3206*/  /*CRC_TABLE_IS_CONST开着引起的*/
{
	#ifdef CRC_TABLE_IS_CONST

	#else

	u16 i;
	u8 j;
	u8 poly, value;
	u8 valid_bits;
	u8 l_bit ;

	if(id<CRC8_ID_MAX)
	{
		valid_bits = (2u << (crc_struct[id].width - 1u)) - 1u;
		//逆序LSB输入
		if (crc_struct[id].refin)
		{
			//poly 以及init 都要先逆序, crc8_table 的 init = 0;
			poly = crc8_reflected(crc_struct[id].poly, crc_struct[id].width);

			for (i = 0u; i < 256u; i++)
			{
				 value = i;
				 for (j = 0u; j < 8u; j++)
				 {
						if (value & 1u)
						{
							value = (value >> 1u) ^ poly;
						}
						else
						{
							value = (value >> 1u);
						}
				 }
				 crc8_table[id][i] = value & valid_bits;
			}
		}
		//正序MSB输入
		else
		{
			//如果位数小于8，poly要左移到最高位
			poly =  crc_struct[id].width < 8u ? crc_struct[id].poly << (8u - crc_struct[id].width) : crc_struct[id].poly;
			l_bit = crc_struct[id].width > 8u ?  CRC8_BIT(crc_struct[id].width - 1u) : 0x80u;

			for (i = 0u; i < 256u; i++) 
			{
					value = crc_struct[id].width > 8u ? i << (crc_struct[id].width - 8u) : i;
					for (j = 0u; j < 8u; j++) 
					{
						if (value & l_bit)
						{
							value = (value << 1) ^ poly;
						}
						else
						{
							value = (value << 1);
						}
					}
					//如果width < 8，那么实际上，crc是在高width位的，需要右移 8 - width
					//但是为了方便后续异或（还是要移位到最高位与*ptr的bit7对齐），所以不处理
					// if (info->width < 8)
					//	  value >>=  8 - info->width;
					// crc8_table[id][i] = value & (2 << (info->width - 1)) - 1);
					crc8_table[id][i] = value &  (crc_struct[id].width < 8u ? 0xff : valid_bits);
			}
		}
	}
	#endif
}

#if 0
void crc8_generate_table(void)
{
		crc8_table_init(&crc_struct[0]);
}
#endif


MEMORY_MAP_ROM_FOR_ASIL u8 crc8_table_set_init_value(u8 id,u8 value)
{
	if(id<CRC8_ID_MAX)
	{
		crc_struct[id].init = value;
	}
        return 1u;
}

MEMORY_MAP_ROM_FOR_ASIL u8 crc8_make_by_table(u8 id,u8 *p_data,u8 len)
{
	//正序
	u8 crc8=0u;
	u8 i;
	if(id<CRC8_ID_MAX)
	{
		crc8 =  crc_struct[id].init;
		for(i=0u; i<len;i++)
		{
			crc8 = crc8_table[id][crc8^*p_data];
			p_data++;
		}
		crc8 ^= crc_struct[id].xorout;
	}
	return(crc8);
}







#endif


MEMORY_MAP_ROM_FOR_ASIL u8 crc_8_make_l1(u8 *u8_data,u8 u8_len)
{
	u8 i, j;
	u8 u8_crc8;
	u8 u8_poly;

	u8_crc8 = CRC8_L1_INIT_VALUE;
	u8_poly = CRC8_L1_POLY_VALUE;

	for (i = 0; i < u8_len; i++)
	{
		u8_crc8 ^= u8_data[i];

		for (j = 0u; j < 8u; j++)
		{
			if (u8_crc8 & 0x80u)
			{
				u8_crc8 = (u8)(u8_crc8 << 1) ^ u8_poly;  /*PRQA S 4571*/
			}
			else
			{
				u8_crc8 <<= 1;
			}
		}
	}

	u8_crc8 ^= (u8)CRC8_L1_XOR_VALUE;
	return u8_crc8;

}


MEMORY_MAP_ROM_FOR_ASIL u8 crc_8_make_l2(u8 *u8_data,u8 u8_len)
{
	u8 i, j;
	u8 u8_crc8;
	u8 u8_poly;

	u8_crc8 = CRC8_L2_INIT_VALUE;
	u8_poly = CRC8_L2_POLY_VALUE;

	for (i = 0; i < u8_len; i++)
	{
		u8_crc8 ^= u8_data[i];

		for (j = 0u; j < 8u; j++)
		{
			if (u8_crc8 & 0x80u)
			{
				u8_crc8 = (u8)(u8_crc8 << 1) ^ u8_poly; /*PRQA S 4571*/
			}
			else
			{
				u8_crc8 <<= 1;
			}
		}
	}

	u8_crc8 ^= (u8)CRC8_L2_XOR_VALUE;  /*PRQA S 2985*/
	return u8_crc8;

}


/*
举例： 00 00 00 00 结果为0X59

							ff ff      ff   ff 结果为0X74

						 F2 01 83   结果为 0X37
*/
#if 0

#define CRC_L1_CHECKSUM_CHECK  0xb4u
#define CRC_L2_CHECKSUM_CHECK  0x5du
u8 g_crc_check[4] = {0u};
void crc_init(void)
{
	u8 i;
	u8 l_buf[8];
	u8 l_checksum[2];
	//检验CRC的结果是否正确
	#ifdef CRC_USE_TABLE
	crc8_table_init(CRC8_ID_FOR_E2E_L1);
	crc8_table_init(CRC8_ID_FOR_E2E_L2);
	#endif

	for(i = 0u; i < 8u; i++)
	{
		/* code */
		l_buf[i] = 0x01u+i;
	}

	#ifdef CRC_USE_TABLE
	l_checksum[0] = crc8_make_by_table(CRC8_ID_FOR_E2E_L1,&l_buf[0],8u);
	l_checksum[1] = crc8_make_by_table(CRC8_ID_FOR_E2E_L2,&l_buf[0],8u);
	#else
	l_checksum[0] = crc_8_make_l1(&l_buf[0],8u);
	l_checksum[1] = crc_8_make_l2(&l_buf[0],8u);
	#endif

	if(l_checksum[0]==CRC_L1_CHECKSUM_CHECK)
	{
		g_crc_check[0]++;
	}
	else
	{
		g_crc_check[1]++;
	}

	if(l_checksum[1]==CRC_L2_CHECKSUM_CHECK)
	{
		g_crc_check[2]++;
	}
	else
	{
		g_crc_check[3]++;
	}
}


#endif
/*END LINE*/
